package com.viknix.threadpool.manager.config.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.viknix.threadpool.manager.common.model.PoolParameterInfo;
import com.viknix.threadpool.manager.common.util.ContentUtil;
import com.viknix.threadpool.manager.common.util.Md5Util;
import com.viknix.threadpool.manager.config.dump.ConfigInfo;
import com.viknix.threadpool.manager.server.dependence.exception.ServerProcessException;
import com.viknix.threadpool.manager.config.service.ConfigService;
import com.viknix.threadpool.manager.config.service.LongPollingService;
import com.viknix.threadpool.manager.repository.entity.ThreadPoolInfoEntity;
import com.viknix.threadpool.manager.repository.mapper.ThreadPoolInfoMapper;
import com.viknix.threadpool.manager.config.convert.ThreadPoolInfoConvert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Map;

import static com.viknix.threadpool.manager.common.constant.Constants.LONG_PULLING_TIMEOUT;

/**
 * @Author: Dongqi
 * @Date: 2021/10/29 10:42
 * @Version 1.0
 * @Description: ConfigServiceImpl
 */
@Slf4j
@Service
public class ConfigServiceImpl implements ConfigService {

    @Autowired
    private ThreadPoolInfoMapper threadPoolInfoMapper;
    @Autowired
    private LongPollingService longPollingService;

    @Override
    public PoolParameterInfo getParameterInfo(String threadPoolId, String projectId, String namespace) {
        ThreadPoolInfoEntity entity = threadPoolInfoMapper.getParameterInfo(threadPoolId, projectId, namespace);
        return ThreadPoolInfoConvert.INSTANCE.convert(entity);
    }

    @Override
    public String doPollingConfig(HttpServletRequest request, HttpServletResponse response, Map<String, String> clientMd5Map, int probeRequestSize) {
        if (isSupportLongPolling(request)) {
            longPollingService.addLongPollingClient(request, response, clientMd5Map, probeRequestSize);
            return HttpServletResponse.SC_OK + "";
        }
        return HttpServletResponse.SC_OK + "";
    }

    private boolean isSupportLongPolling(HttpServletRequest req) {
        return StringUtils.isNotBlank(req.getHeader(LONG_PULLING_TIMEOUT));
    }

    @Override
    public int insertOrUpdate(PoolParameterInfo parameterInfo) {
        int result = 0;
        ThreadPoolInfoEntity entity = ThreadPoolInfoConvert.INSTANCE.convert(parameterInfo);
        entity.setContent(ContentUtil.getPoolContent(parameterInfo));
        entity.setMd5(Md5Util.getTpContentMd5(parameterInfo));
        entity.setDeleteFlag(0);
        try {
            result = addConfigInfo(entity);
        } catch (Exception e) {
            result = updateConfigInfo(entity);
        }
        return result;
    }

    @Override
    public String getContentMd5(String groupKey) {
        String[] split = groupKey.split("\\+");
        PoolParameterInfo configInfo = getParameterInfo(split[0], split[1], split[2]);
        if (configInfo == null) {
            String errorMessage = String.format("config is null. tpId :: %s, itemId :: %s, tenantId :: %s", split[0], split[1], split[2]);
            log.error(">>>" + errorMessage);
            throw new ServerProcessException(errorMessage);
        }
        return Md5Util.getTpContentMd5(configInfo);
    }

    private int addConfigInfo(ThreadPoolInfoEntity entity) {
        entity.setCreatedTime(new Date());
        return threadPoolInfoMapper.insert(entity);
    }

    private int updateConfigInfo(ThreadPoolInfoEntity entity) {
        entity.setLastUpdTime(new Date());
        return threadPoolInfoMapper.updateByIdentification(entity);
    }

    @Override
    public ConfigInfo getConfigInfo(String threadPoolId, String projectId, String namespace) {
        Map<String, Object> map = threadPoolInfoMapper.getConfigInfo(threadPoolId, projectId, namespace);
        if (map != null && map.size() > 0) {
            return BeanUtil.fillBeanWithMap(map, new ConfigInfo(), false);
        }
        return null;
    }
}
